home *** CD-ROM | disk | FTP | other *** search
- /*
- File: SampleStorageDriver.c
-
- Contains: All functions for the Class driverto access and control the device
-
- Version: 1.1
-
- Copyright: © 1998-1999 by Apple Computer, Inc., all rights reserved.
-
- File Ownership:
-
- DRI: Craig Keithley
-
- Other Contact: xxx put other contact here xxx
-
- Technology: USB Drivers
-
- Writers:
-
- (TM) Tim McLeod
- (CJK) Craig Keithley
-
- Change History (most recent first):
-
- <USB3> 2/16/99 TM Added an error code for class not configured. Changed all places
- where the class driver was returning kNotConfigured to
- kClassNotConfiguredErr. kNotConfigured is enumed to zero which
- when returned as an error code makes the caller think that it is
- getting a noErr.
- <USB2> 1/11/99 CJK update to use sources from 1.1f3 DDK
-
- */
-
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- includes
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- #include <Devices.h>
- #include <DriverServices.h>
- #include <Interrupts.h>
- #include <LowMem.h>
- #include <Folders.h>
- #include <MacTypes.h>
- #include <CodeFragments.h>
-
- #include <USB.h>
-
- #include "SampleStorageDriverAPI.h"
- #include "SampleStorageDeviceID.h"
- #include "SampleStorageDriver.h"
-
- extern TheStorageClassDispatchTable;
-
- enum
- {
- kCString = 0, // StateStr, USBStatusStr selector
- kPString // StateStr, USBStatusStr selector
- };
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- globals
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- static Boolean gBeenThereDoneThat = false; // Flag indicating if this driver has been called before
-
- static Boolean gConfigured = false; // No calls to dispatch table until this is true.
-
- static UInt32 gConfigureStatus; // Current state of cinfiguration
-
- static Boolean gOKToRemoval = true; // Used in StorageClassDriverNotifyProc to prevent removal by expert
-
- static struct StorageClassInfo gStorageClassInfo; // Holds all of the common items
-
- static struct StorageClassTransactionPB gInterruptPB; // Used only for the interrupt pipe
-
- static struct StorageClassStatusPB gGetStatusPB; // Used only for the USB Get Status request
-
- static struct StorageClassControlPB gControlPB; // Used only for aborting a R/W transaction
-
- static struct StorageClassTransactionPB gCommandPB; // Used only by StorageClassDriverExecuteCommand
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- prototypes
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- static void InitParamBlock(USBDeviceRef theDeviceRef, USBPB* paramblock);
-
- static Boolean ImmediateError(OSStatus err);
-
- static void StorageDeviceConfigureCompletion(USBPB* pb);
-
- static void StorageDeviceInitiateConfiguration(USBPB* pb);
-
- static OSStatus StorageClassDriverGetStatus( StorageStatusPBPtr statusPBPtr );
-
- static OSStatus StorageClassDriverAbortTransaction( StorageControlPBPtr controlPBPtr );
-
- // Completion routines
-
- static void ReadBlockCompletion(USBPB* usbPB);
-
- static void WriteBlockCompletion(USBPB* usbPB);
-
- static void ExecuteCommandCompletion(USBPB* usbPB);
-
- static void ExecuteBufferedCommandCompletion(USBPB* usbPB);
-
- static void GetStatusCompletion(USBPB* usbPB);
-
- static void AbortTransactionCompletion(USBPB* usbPB);
-
- //****************************************************************************************************
-
- #if DEBUG
-
- static void
- HexStr( unsigned long v,
- unsigned char *p )
- {
- int shift;
-
- for ( shift = 32-4; shift >= 0; shift -= 4 )
- {
- char c = (v >> shift) & 0x0F;
- *p++ = c + (c > 9? ('A'-10): '0');
- }
- }
-
- static unsigned char *
- USBStatusStr( OSStatus usbStatus,
- int kind )
- {
- unsigned char *p;
-
- switch ( usbStatus )
- {
- case kUSBInternalErr: p = "\p" kStrStorageClass "Internal error"; break;
- case kUSBUnknownDeviceErr: p = "\p" kStrStorageClass "Unknown device"; break;
- case kUSBUnknownPipeErr: p = "\p" kStrStorageClass "Unknown pipe"; break;
- case kUSBTooManyPipesErr: p = "\p" kStrStorageClass "Too many pipes"; break;
- case kUSBIncorrectTypeErr: p = "\p" kStrStorageClass "Incorrect type"; break;
- case kUSBRqErr: p = "\p" kStrStorageClass "Request error"; break;
- case kUSBUnknownRequestErr: p = "\p" kStrStorageClass "Unknown request"; break;
- case kUSBTooManyTransactionsErr: p = "\p" kStrStorageClass "Too many transactions"; break;
- case kUSBAlreadyOpenErr: p = "\p" kStrStorageClass "Already open"; break;
- case kUSBNoDeviceErr: p = "\p" kStrStorageClass "No device"; break;
- case kUSBDeviceErr: p = "\p" kStrStorageClass "Device error"; break;
- case kUSBOutOfMemoryErr: p = "\p" kStrStorageClass "Out of memory"; break;
- case kUSBNotFound: p = "\p" kStrStorageClass "USB Not found"; break;
- case kUSBLinkErr: p = "\p" kStrStorageClass "Link Err"; break;
- case kUSBCRCErr: p = "\p" kStrStorageClass "Comms/Device err, bad CRC"; break;
- case kUSBBitstufErr: p = "\p" kStrStorageClass "Comms/Device err, bitstuffing"; break;
- case kUSBDataToggleErr: p = "\p" kStrStorageClass "Comms/Device err, Bad data toggle"; break;
- case kUSBEndpointStallErr: p = "\p" kStrStorageClass "Device didn't understand"; break;
- case kUSBNotRespondingErr: p = "\p" kStrStorageClass "No device, device hung"; break;
- case kUSBPIDCheckErr: p = "\p" kStrStorageClass "Comms/Device err, PID CRC error"; break;
- case kUSBWrongPIDErr: p = "\p" kStrStorageClass "Comms/Device err, Bad or wrong PID"; break;
- case kUSBOverRunErr: p = "\p" kStrStorageClass "Packet too large or more data than buffer"; break;
- case kUSBUnderRunErr: p = "\p" kStrStorageClass "Less data than buffer"; break;
- case kUSBRes1Err: p = "\p" kStrStorageClass "kUSBRes1Err"; break;
- case kUSBRes2Err: p = "\p" kStrStorageClass "kUSBRes1Err"; break;
- case kUSBBufOvrRunErr: p = "\p" kStrStorageClass "Buffer over run error"; break;
- case kUSBBufUnderRunErr: p = "\p" kStrStorageClass "Buffer under run error"; break;
- case kUSBNotSent1Err: p = "\p" kStrStorageClass "Transaction not sent1"; break;
- case kUSBNotSent2Err: p = "\p" kStrStorageClass "Transaction not sent2"; break;
- default:
- p = "\p" kStrStorageClass "Unknown error nnnnnnnn";
- HexStr( usbStatus, p + *p - 8 + 1 );
- break;
- }
-
- return kind == kPString? p: p + 1;
- }
-
-
- static unsigned char*
- StateStr( OSStatus refCon,
- int kind )
- {
- unsigned char *p;
-
- refCon &= ~(kCompletionPending | kRetryTransaction | kAsyncTransaction | kReturnFromDriver);
- switch ( refCon )
- {
- case kSetConfig: p = kStrStorageClass "kSetConfig"; break;
- case kGetFullConfiguration: p = kStrStorageClass "kGetFullConfiguration"; break;
- case kFindStorageInterface: p = kStrStorageClass "kFindStorageInterface"; break;
- case kStorageConfigureInterface: p = kStrStorageClass "kStorageConfigureInterface"; break;
-
- case kNewInterfaceRef: p = kStrStorageClass "kNewInterfaceRef"; break;
- case kStorageFindInterruptPipe: p = kStrStorageClass "kStorageFindInterruptPipe"; break;
- case kStorageFindBulkInPipe: p = kStrStorageClass "kStorageFindBulkInPipe"; break;
- case kStorageFindBulkOutPipe: p = kStrStorageClass "kStorageFindBulkOutPipe"; break;
-
- case kStorageReadInterrupt: p = kStrStorageClass "kStorageReadInterrupt"; break;
-
- case kStorageExecuteCommand: p = kStrStorageClass "kStorageExecuteCommand"; break;
- case kStorageExecuteCommandCompletion: p = kStrStorageClass "kStorageExecuteCommandCompletion"; break;
- case kStorageBulkIOComplete: p = kStrStorageClass "kStorageBulkIOComplete"; break;
- case kStorageGetStatus: p = kStrStorageClass "kStorageGetStatus"; break;
- case kStorageGetStatusBulkRead: p = kStrStorageClass "kStorageGetStatusBulkRead"; break;
-
- default:
- p = "\pUnknown state nnnnnnnn";
- HexStr( refCon, p + *p - 8 + 1 );
- break;
- }
- return kind == kPString? p: p + 1;
- }
- #endif
-
- static unsigned char
- HiHex( int v )
- {
- unsigned char hinibble = (v >> 4) & 0x0f;
- return hinibble + ((hinibble > 9)? ('A'-10): '0');
- }
-
-
- static unsigned char
- LoHex( int v )
- {
- unsigned char lonibble = v & 0x0f;
- return lonibble + ((lonibble > 9)? ('A'-10): '0');
- }
-
-
- static void
- InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
- {
- paramblock->usbReference = theDeviceRef;
- paramblock->pbVersion = kUSBCurrentPBVersion;
- paramblock->pbLength = sizeof(USBPB);
- paramblock->usb.cntl.WIndex = 0;
- paramblock->usbBuffer = nil;
- paramblock->usbStatus = noErr;
- paramblock->usbReqCount = 0;
- paramblock->usb.cntl.WValue = 0;
- paramblock->usbFlags = 0;
- }
-
-
- static Boolean
- ImmediateError(OSStatus err)
- {
- return((err != kUSBPending) && (err != noErr) );
- }
-
-
- OSStatus
- GetUSBVersion(UInt32* usbVersion)
- {
- OSStatus result;
-
- result = Gestalt('usbv', usbVersion);
-
- return result;
- }
-
-
- OSErr
- GetInterfaceDescriptor( LogicalAddress pConfigDesc,
- UInt32 ReqInterface,
- USBInterfaceDescriptorPtr * hInterfaceDesc)
- {
- UInt32 totalLength;
- void * pEndOfDescriptors;
- USBInterfaceDescriptorPtr pMyIntDesc;
- USBDescriptorHeaderPtr pCurrentDesc;
- UInt32 anAddress,
- anOffset;
-
- totalLength = ((USBConfigurationDescriptorPtr)pConfigDesc)->totalLength;
- pEndOfDescriptors = (Ptr)pConfigDesc + totalLength; // get the total length and add it to the start of the config space
- pCurrentDesc = (USBDescriptorHeaderPtr)pConfigDesc; // point the currentdesc to the start of the config space
-
- while (pCurrentDesc < pEndOfDescriptors) // as long as we haven't exhausted all the descriptors
- {
- if (pCurrentDesc->descriptorType == kUSBInterfaceDesc) // look at the current descriptor
- {
- pMyIntDesc = (USBInterfaceDescriptorPtr)pCurrentDesc; // if it's an interface descriptor
- if (pMyIntDesc->interfaceNumber == ReqInterface) // see if it's the request descriptor
- {
- *hInterfaceDesc = pMyIntDesc; // if it is, then return with hInterfaceDesc set to the
- return kUSBNoErr; // current descriptor pointer
- }
- }
- anAddress = (unsigned long) pCurrentDesc; // Nope, that either wasn't an interface descriptor
- anOffset = (unsigned long) pCurrentDesc->length;
- anAddress += anOffset;
- pCurrentDesc = (USBDescriptorHeaderPtr) anAddress;
- } // or it was, but not the droid we're looking for.
- return -1;
- }
-
- //****************************************************************************************************
- //
- // StorageClassDriverAPI.c calls end up here...
- //
- //****************************************************************************************************
-
- OSStatus
- StorageClassDriverInitialize(void)
- {
- return noErr;
- }
-
-
- OSStatus
- StorageClassDriverControl( UInt32 theControlSelector,
- void *theControlData)
- {
- #pragma unused (theControlData)
-
- OSStatus status;
-
- switch (theControlSelector)
- {
- case kControlDisableRemoval:
- gOKToRemoval = false;
- status = noErr;
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriver: kControlDisableRemoval", 0) );
- break;
-
- case kControlEnableRemoval:
- gOKToRemoval = true;
- status = noErr;
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriver: kControlEnableRemoval", 0) );
- break;
-
- default:
- status = controlErr;
- break;
- }
- return status;
- }
-
-
- OSStatus
- StorageClassDriverStatus( UInt32 theInfoSelector,
- void *theInfo)
- {
- OSStatus status;
-
- switch (theInfoSelector)
- {
- case kStatusConfiguration: // Return the current confifuration status
- *((UInt32*) theInfo) = gConfigureStatus;
- status = noErr;
- break;
-
- case kStatusDeviceStatus:
- status = StorageClassDriverGetStatus( (StorageStatusPBPtr) theInfo );
- break;
-
- case kStatusRemovalStatus:
- *((Boolean*) theInfo) = gOKToRemoval;
- status = noErr;
- break;
-
- default:
- status = statusErr;
- break;
- }
- return status;
- }
-
-
- // All device requests come through here
- OSStatus
- StorageClassDriverExecuteCommand( StorageExecuteCommandPBPtr cmdPBPtr )
- {
- OSStatus myErr;
- // IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriverExecuteCommand", 0) );
-
- // Make sure we have been able to configure the device
- if (gConfigured == false)
- {
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriver StorageClassDriverExecuteCommand not configured", 0) );
- return kClassNotConfiguredErr;
- }
-
- // check if we already have a read in progress, if so return error.
- if (gCommandPB.busy == true)
- {
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriver StorageClassDriverExecuteCommand busy", 0) );
- return kCommandBusyError;
- }
-
- cmdPBPtr->status = kRequestPending;
-
- BlockZero(&gCommandPB, sizeof(StorageClassTransactionPB));
-
- gCommandPB.busy = true;
-
- InitParamBlock(gStorageClassInfo.interfaceRef, &gCommandPB.usbPB);
-
- // Get a local copy of the callers cdb
- BlockCopy(&cmdPBPtr->cdb[0], &gCommandPB.cdb[0], kCDBSize);
-
- gCommandPB.flags = cmdPBPtr->flags;
-
- gCommandPB.userPBPtr = (StorageExecuteCommandPBPtr) cmdPBPtr; // Save the ptr to the callers PB
-
- gCommandPB.usbPB.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
-
- gCommandPB.usbPB.usb.cntl.BRequest = 0;
- gCommandPB.usbPB.usb.cntl.WValue = 0;
- gCommandPB.usbPB.usb.cntl.WIndex = 0;
-
- gCommandPB.usbPB.usbBuffer = (Ptr)&gCommandPB.cdb[0];
- gCommandPB.usbPB.usbReqCount = kCDBSize;
- gCommandPB.usbPB.usbFlags = 0;
-
- gCommandPB.usbPB.usbRefcon = kStorageExecuteCommand;
-
- gCommandPB.usbPB.usbCompletion = (USBCompletion)ExecuteCommandCompletion; // Don't use double buffering for builk I/O
-
- myErr = USBDeviceRequest(&gCommandPB.usbPB);
-
- return myErr;
- }
-
- static void ExecuteCommandCompletion(USBPB* usbPB)
- {
- OSStatus myErr;
- StorageExecuteCommandPBPtr cmdPBPtr;
-
- // Retrieve the callers pb
- cmdPBPtr = (StorageExecuteCommandPBPtr) gCommandPB.userPBPtr;
-
- // IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, StateStr(usbPB->usbRefcon, kPString) , 5 ) );
-
- switch(usbPB->usbRefcon)
- {
- case kStorageExecuteCommand: // Device request completion
- // First check to see if an error occurred on the command out
- if (usbPB->usbStatus != noErr)
- {
- // Clear stalled control pipe
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClass: kStorageExecuteCommand error. usbStatus:" , usbPB->usbStatus ) );
- USBClearPipeStallByReference(usbPB->usbReference);
- cmdPBPtr->status = usbPB->usbStatus;
-
- gCommandPB.busy = false;
- if(cmdPBPtr->completionProc != nil)
- {
- (*cmdPBPtr->completionProc)((StorageExecuteCommandPBPtr) cmdPBPtr);
- }
- break;
- }
-
- // If there is to be no data transfer then we are done and can return to the caller
- if (gCommandPB.flags & kStorageNoData)
- {
- cmdPBPtr->status = usbPB->usbStatus;
-
- gCommandPB.busy = false;
- (*cmdPBPtr->completionProc)((StorageExecuteCommandPBPtr) cmdPBPtr);
-
- break;
- }
- // Setup the usb pb for either bulk in or out
- if (gCommandPB.flags & kStorageDataIn)
- InitParamBlock(gStorageClassInfo.readPipeRef, usbPB);
- else if (gCommandPB.flags & kStorageDataOut)
- InitParamBlock(gStorageClassInfo.writePipeRef, usbPB);
-
- // Check to see if the amount of data to be transferred is greater
- // than kUSBMaxBulkTransfer. This is to get around an issue with
- // the USB Manager/USL where the amount of data transferred per
- // Bulk Request needs to be limited to a specific amount
- if ( cmdPBPtr->expectedCount > kUSBMaxBulkTransfer )
- {
- usbPB->usbReqCount = kUSBMaxBulkTransfer;
- }
- else
- {
- usbPB->usbReqCount = cmdPBPtr->expectedCount;
- }
-
- usbPB->usbRefcon = kStorageBulkIOComplete;
- usbPB->usbActCount = 0;
- usbPB->usbBuffer = cmdPBPtr->userBuffer;
- usbPB->usbCompletion = (USBCompletion)ExecuteCommandCompletion;
-
- // Start a bulk in or out transaction
- if (gCommandPB.flags & kStorageDataIn)
- myErr = USBBulkRead(&gCommandPB.usbPB);
- else if (gCommandPB.flags & kStorageDataOut)
- myErr = USBBulkWrite(&gCommandPB.usbPB);
-
- if (ImmediateError(myErr))
- {
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, kUSBInternalErr, "\pStorageClass: kStorageExecuteCommand - immediate error", myErr) );
- cmdPBPtr->actualCount = usbPB->usbActCount;
- cmdPBPtr->status = myErr;
- gCommandPB.busy = false;
- (*cmdPBPtr->completionProc)((StorageExecuteCommandPBPtr) cmdPBPtr);
- }
- break;
-
- case kStorageBulkIOComplete:
-
- cmdPBPtr->actualCount = usbPB->usbActCount; // Update the users byte count
- cmdPBPtr->status = usbPB->usbStatus; // and status
-
- if (usbPB->usbStatus != noErr) // Clear a possible pipe stall
- {
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClass: kStorageBulkIOComplete error. usbStatus:" , usbPB->usbStatus ) );
- USBClearPipeStallByReference(usbPB->usbReference);
- }
- else if ( cmdPBPtr->actualCount != cmdPBPtr->expectedCount)
- {
- // If we have not yet transfered all the data and there are no Errors
- // Setup the usb pb for either bulk in or out
- if (gCommandPB.flags & kStorageDataIn)
- {
- InitParamBlock(gStorageClassInfo.readPipeRef, usbPB);
- }
- else if (gCommandPB.flags & kStorageDataOut)
- {
- InitParamBlock(gStorageClassInfo.writePipeRef, usbPB);
- }
-
- if ( (cmdPBPtr->expectedCount - cmdPBPtr->actualCount) > kUSBMaxBulkTransfer )
- {
- usbPB->usbReqCount = kUSBMaxBulkTransfer;
- }
- else
- {
- usbPB->usbReqCount = (cmdPBPtr->expectedCount - cmdPBPtr->actualCount);
- }
-
- usbPB->usbRefcon = kStorageBulkIOComplete;
- usbPB->usbActCount = 0;
- usbPB->usbBuffer = (cmdPBPtr->userBuffer) + (cmdPBPtr->actualCount);
- usbPB->usbCompletion = (USBCompletion)ExecuteCommandCompletion;
-
- // Continue a bulk in or out transaction
- if (gCommandPB.flags & kStorageDataIn)
- {
- myErr = USBBulkRead(&gCommandPB.usbPB);
- }
- else if (gCommandPB.flags & kStorageDataOut)
- {
- myErr = USBBulkWrite(&gCommandPB.usbPB);
- }
-
- if (ImmediateError(myErr))
- {
- USBExpertFatalError(gStorageClassInfo.deviceRef, kUSBInternalErr, "\pStorageClass: kStorageExecuteCommand - immediate error", myErr);
- cmdPBPtr->status = myErr;
- gCommandPB.busy = false;
- if(cmdPBPtr->completionProc != nil)
- {
- (*cmdPBPtr->completionProc)((StorageExecuteCommandPBPtr) cmdPBPtr);
- }
- }
- break;
- }
-
- gCommandPB.busy = false;
- (*cmdPBPtr->completionProc)((StorageExecuteCommandPBPtr) cmdPBPtr);
- break;
-
- default:
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, kUSBInternalErr, "\pStorageClass: ExecuteCommandCompletion - unknown state!", 5) );
- cmdPBPtr->actualCount = 0;
- cmdPBPtr->status = kUSBInternalErr;
-
- gCommandPB.busy = false;
- (*cmdPBPtr->completionProc)((StorageExecuteCommandPBPtr) cmdPBPtr);
- break;
- }
- }
-
- OSStatus
- StorageClassDriverGetStatus( StorageStatusPBPtr statusPBPtr )
- {
- OSStatus myErr;
-
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\p • StorageClassDriverGetStatus", 0) );
-
- // Make sure we have been able to configure the device
- if (gConfigured == false)
- {
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriver StorageClassDriverExecuteCommand not configured", 0) );
- return kClassNotConfiguredErr;
- }
-
- // check if we already have a status request in progress, if so return error.
- if (gGetStatusPB.busy == true)
- {
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriver StorageClassDriverGetStatus busy", 0) );
- return kCommandBusyError;
- }
-
- BlockZero(&gGetStatusPB, sizeof(StorageClassStatusPB));
-
- gGetStatusPB.busy = true;
-
- gGetStatusPB.userPBPtr = statusPBPtr;
-
- InitParamBlock(gStorageClassInfo.interfaceRef, &gGetStatusPB.usbPB);
-
- gGetStatusPB.usbPB.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBDevice);
-
- gGetStatusPB.usbPB.usb.cntl.BRequest = kUSBRqGetStatus;
- gGetStatusPB.usbPB.usb.cntl.WIndex = 0;
- gGetStatusPB.usbPB.usb.cntl.WValue = 0;
-
- gGetStatusPB.usbPB.usbBuffer = (Ptr)&gGetStatusPB.status[0];
- gGetStatusPB.usbPB.usbReqCount = kStatusSize;
- gGetStatusPB.usbPB.usbFlags = 0;
-
- gGetStatusPB.usbPB.usbRefcon = kStorageGetStatus;
- gGetStatusPB.usbPB.usbCompletion = (USBCompletion)GetStatusCompletion;
-
- myErr = USBDeviceRequest(&gGetStatusPB.usbPB);
-
- return myErr;
- }
-
-
-
- static void GetStatusCompletion(USBPB* usbPB)
- {
- StorageStatusPBPtr userPBPtr;
-
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, StateStr(usbPB->usbRefcon, kPString) , 6 ) );
-
- // Retrieve the callers pb
- userPBPtr = (StorageStatusPBPtr) gGetStatusPB.userPBPtr;
-
- userPBPtr->status = usbPB->usbStatus;
- userPBPtr->deviceStatus[0] = gGetStatusPB.status[0];
- userPBPtr->deviceStatus[1] = gGetStatusPB.status[1];
-
- gGetStatusPB.busy = false;
- (*userPBPtr->completionProc)((StorageExecuteCommandPBPtr) userPBPtr);
- }
-
-
- OSStatus
- StorageClassDriverAbortTransaction( StorageControlPBPtr controlPBPtr )
- {
- OSStatus myErr;
-
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\p • StorageClassDriverAbortTransaction", 0) );
-
- // Make sure we have been able to configure the device
- if (gConfigured == false)
- {
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriver StorageClassDriverAbortTransaction not configured", 0) );
- return kClassNotConfiguredErr;
- }
-
- // check if we already have a status request in progress, if so return error.
- if (gControlPB.busy == true)
- {
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriver StorageClassDriverAbortTransaction busy", 0) );
- return kCommandBusyError;
- }
-
- BlockZero(&gControlPB, sizeof(StorageControlPB));
-
- gControlPB.busy = true;
-
- gControlPB.userPBPtr = controlPBPtr;
-
- InitParamBlock(gStorageClassInfo.interfaceRef, &gControlPB.usbPB);
-
- gControlPB.usbPB.usb.cntl.BMRequestType = 0x02; // Clear feature
-
- gControlPB.usbPB.usb.cntl.BRequest = kUSBRqClearFeature;
-
- if (controlPBPtr->selector == 0) // Abort read pipe
- gControlPB.usbPB.usb.cntl.WIndex = 0x82;
- else // Abort write pipe
- gControlPB.usbPB.usb.cntl.WIndex = 0x01;
-
- gControlPB.usbPB.usb.cntl.WValue = 0; // 0 = clear endpoint stall
-
- gControlPB.usbPB.usbBuffer = nil;
- gControlPB.usbPB.usbReqCount = 0;
- gControlPB.usbPB.usbFlags = 0;
-
- gControlPB.usbPB.usbRefcon = kStorageGetStatus;
- gControlPB.usbPB.usbCompletion = (USBCompletion)AbortTransactionCompletion;
-
- myErr = USBDeviceRequest(&gControlPB.usbPB);
-
- return myErr;
- }
-
-
-
- static void AbortTransactionCompletion(USBPB* usbPB)
- {
- StorageControlPBPtr userPBPtr;
-
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, StateStr(usbPB->usbRefcon, kPString) , 7 ) );
-
- // Retrieve the callers pb
- userPBPtr = (StorageControlPBPtr) gControlPB.userPBPtr;
-
- userPBPtr->status = usbPB->usbStatus;
-
- gControlPB.busy = false;
- (*userPBPtr->completionProc)((StorageExecuteCommandPBPtr) userPBPtr);
- }
-
-
- static void ReadInterruptCompletion(USBPB* usbPB)
- {
- gStorageClassInfo.transDepth--;
-
- if (usbPB->usbStatus == kUSBEndpointStallErr)
- {
- USBClearPipeStallByReference(gStorageClassInfo.interruptPipeRef);
- }
- InitParamBlock(gStorageClassInfo.interruptPipeRef, usbPB);
-
- usbPB->usbBuffer = (Ptr)gStorageClassInfo.interruptReport;
- usbPB->usbReqCount = 0x02;
- usbPB->usbRefcon = kStorageReadInterrupt;
- usbPB->usbCompletion = (USBCompletion)ReadInterruptCompletion;
-
- StorageDeviceInitiateConfiguration(usbPB);
- }
-
- void
- StorageDeviceInitiateConfiguration(USBPB *usbPB)
- {
- OSStatus myErr;
- StorageClassTransactionPB* pTransPB = (StorageClassTransactionPB*) usbPB;
-
- gStorageClassInfo.transDepth++;
-
- if ((gStorageClassInfo.transDepth < 0) || (gStorageClassInfo.transDepth > kMaxTransitions))
- {
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass: Illegal Transaction Depth", usbPB->usbRefcon) );
- gConfigureStatus = kConfigureFailed;
- }
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, StateStr(usbPB->usbRefcon, kPString) , 2 ) );
-
- switch(usbPB->usbRefcon & ~kRetryTransaction)
- {
- case kGetFullConfiguration:
- InitParamBlock(gStorageClassInfo.deviceRef, usbPB);
-
- usbPB->usb.cntl.WIndex = 0; // First try configuration 0, if it doesn't succeed, then try config 1
- usbPB->usbRefcon |= kCompletionPending;
- usbPB->usbCompletion = (USBCompletion)StorageDeviceConfigureCompletion;
-
- myErr = USBGetFullConfigurationDescriptor(usbPB);
- if(ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass: USBGetFullConfiguration (#0) - immediate error", myErr) );
- }
- break;
-
- case kSetConfig:
- InitParamBlock(gStorageClassInfo.deviceRef, usbPB);
-
- usbPB->usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);
- usbPB->usb.cntl.BRequest = kUSBRqSetConfig;
- usbPB->usb.cntl.WValue = gStorageClassInfo.pFullConfigDescriptor->configValue; // Use configuration ID value from descriptor
- usbPB->usbRefcon |= kCompletionPending;
-
- usbPB->usbCompletion = (USBCompletion)StorageDeviceConfigureCompletion;
-
- myErr = USBDeviceRequest(usbPB);
- if(ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass: kSetConfig - immediate error", myErr) );
- }
- break;
-
- case kFindStorageInterface:
- InitParamBlock(gStorageClassInfo.deviceRef, usbPB);
- usbPB->usbActCount = 0;
-
- usbPB->usbClassType = kDriverClassID;
- usbPB->usbSubclass = kDriverSubClassID;
- usbPB->usbProtocol = 0;
- usbPB->usb.cntl.WValue = 0;
- usbPB->usbRefcon |= kCompletionPending;
- usbPB->usbCompletion = (USBCompletion)StorageDeviceConfigureCompletion;
-
- myErr = USBFindNextInterface(usbPB);
- if(ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass: kFindStorageInterface - immediate error", myErr) );
- }
- break;
-
- case kNewInterfaceRef:
- InitParamBlock(gStorageClassInfo.deviceRef, usbPB);
- // Note: gStorageClassInfo.usbWIndex will be set to zero by InitParamBlock
- // so set it again to gStorageClassInfo.interfaceIndex before calling USBNewInterfaceRef
- usbPB->usbActCount = 0;
- usbPB->usb.cntl.WIndex = gStorageClassInfo.interfaceNumber;
- usbPB->usbRefcon |= kCompletionPending;
- usbPB->usbCompletion = (USBCompletion)StorageDeviceConfigureCompletion;
-
- myErr = USBNewInterfaceRef(usbPB);
- if(ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass: kNewInterfaceRef - immediate error", myErr) );
- }
- break;
-
- case kStorageConfigureInterface:
- InitParamBlock(gStorageClassInfo.interfaceRef, usbPB);
-
- usbPB->usbActCount = 0;
- usbPB->usbCompletion = (USBCompletion)StorageDeviceConfigureCompletion;
- usbPB->usbRefcon |= kCompletionPending;
-
- gStorageClassInfo.interfaceNumber = 0; // Find First calls 'FindNextInterface' with WIndex = 0
- // Find Next calls 'FindNextInterface' with WIndex = InterfaceNumber
-
- myErr = USBConfigureInterface(usbPB);
- if (ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, kUSBInternalErr, "\pStorageClass: kStorageConfigureInterface - immediate error", myErr) );
- }
- break;
-
- case kStorageFindInterruptPipe:
- InitParamBlock(gStorageClassInfo.interfaceRef, usbPB);
-
- usbPB->usbFlags = kUSBIn;
- usbPB->usbClassType = kUSBInterrupt;
- usbPB->usbCompletion = (USBCompletion)StorageDeviceConfigureCompletion;
- usbPB->usbRefcon |= kCompletionPending;
-
- myErr = USBFindNextPipe( usbPB );
- if (ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, kUSBInternalErr, "\pStorageClass: kStorageFindInterruptPipe - immediate error", myErr) );
- usbPB->usbRefcon = kReturnFromDriver;
- }
- break;
-
- case kStorageFindBulkInPipe:
- InitParamBlock(gStorageClassInfo.interfaceRef, usbPB);
-
- usbPB->usbFlags = kUSBIn;
- usbPB->usbClassType = kUSBBulk;
- usbPB->usbCompletion = (USBCompletion)StorageDeviceConfigureCompletion;
- usbPB->usbRefcon |= kCompletionPending;
-
- myErr = USBFindNextPipe( usbPB );
- if (ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, kUSBInternalErr, "\pStorageClass: kStorageFindBulkInPipe - immediate error", myErr) );
- usbPB->usbRefcon = kReturnFromDriver;
- }
- break;
-
- case kStorageFindBulkOutPipe:
- InitParamBlock(gStorageClassInfo.interfaceRef, usbPB);
-
- usbPB->usbFlags = kUSBOut;
- usbPB->usbClassType = kUSBBulk;
- usbPB->usbCompletion = (USBCompletion)StorageDeviceConfigureCompletion;
- usbPB->usbRefcon |= kCompletionPending;
-
- myErr = USBFindNextPipe( usbPB );
- if (ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, kUSBInternalErr, "\pStorageClass: kStorageFindBulkOutPipe - immediate error", myErr) );
- usbPB->usbRefcon = kReturnFromDriver;
- }
- break;
-
- case kStorageReadInterrupt:
- InitParamBlock(gStorageClassInfo.interruptPipeRef, usbPB);
-
- usbPB->usbBuffer = (Ptr)gStorageClassInfo.interruptReport;
- usbPB->usbReqCount = 0x02;
- usbPB->usbCompletion = (USBCompletion)ReadInterruptCompletion;
- usbPB->usbRefcon |= kCompletionPending;
-
- myErr = USBIntRead(usbPB);
- if(ImmediateError(myErr))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, kUSBInternalErr, "\pStorageClass: kStorageReadInterrupt - immediate error", myErr) );
- }
- break;
-
- case kReturnFromDriver:
- break;
-
- default:
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass - Transaction initiated with bad refcon value", usbPB->usbRefcon) );
- usbPB->usbRefcon = kUndefined + kReturnFromDriver;
- break;
- }
-
- // At this point the control is returned to the system. If a USB transaction
- // has been initiated, then it will call the Complete procs
- // (below) to handle the results of the transaction.
- }
-
- static void
- StorageDeviceConfigureCompletion(USBPB *usbPB)
- {
- StorageClassTransactionPB* pTransPB = (StorageClassTransactionPB*) usbPB;
- USBInterfaceDescriptorPtr pInterfaceDescriptor;
- UInt32 i;
-
- gStorageClassInfo.transDepth--;
-
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, StateStr(usbPB->usbRefcon, kPString) , 3 ) );
-
- if ((gStorageClassInfo.transDepth < 0) || (gStorageClassInfo.transDepth > 1))
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass - Illegal Transaction Depth", gStorageClassInfo.transDepth) );
- }
-
- // We should only retry if the error is a USB transaction problem
- // Device errors are handled outside of the state machine.
- if ((usbPB->usbStatus != noErr) && (usbPB->usbStatus != kUSBPending))
- {
- IF_DEBUG( USBExpertStatus(usbPB->usbReference, "\pStorage Driver: Completion Error", usbPB->usbStatus) );
- usbPB->usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
- usbPB->usbRefcon |= kRetryTransaction;
- gStorageClassInfo.retryCount--;
- if (!gStorageClassInfo.retryCount)
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass: Too many retries", usbPB->usbRefcon) );
- usbPB->usbRefcon = kReturnFromDriver;
- return;
- }
- }
- else
- {
- usbPB->usbRefcon &= ~kRetryTransaction;
- gStorageClassInfo.retryCount = kStorageRetryCount;
- }
-
- if (usbPB->usbRefcon & kCompletionPending)
- {
- usbPB->usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
- switch(usbPB->usbRefcon)
- {
- case kGetFullConfiguration:
- usbPB->usbRefcon = kSetConfig;
- gStorageClassInfo.pFullConfigDescriptor = usbPB->usbBuffer; // Save the config descriptor
- if (gStorageClassInfo.pFullConfigDescriptor == nil)
- {
- gConfigureStatus = kConfigureFailed;
- usbPB->usbRefcon = kReturnFromDriver;
-
- IF_DEBUG( USBExpertFatalError(usbPB->usbReference, kUSBInternalErr, "\pStorageClass: USBGetFullConfiguration - pointer is nil", usbPB->usbRefcon) );
- }
- break;
-
- case kSetConfig:
- BlockCopy( (void *) &gStorageClassInfo.pFullConfigDescriptor,
- (void *) &gStorageClassInfo.partialConfigDescriptor,
- (Size) (sizeof(USBConfigurationDescriptor) ) );
-
- for (i=0; i < gStorageClassInfo.partialConfigDescriptor.numInterfaces; i++)
- {
- gStorageClassInfo.interfaceRefArray[i] = 0;
-
- GetInterfaceDescriptor( gStorageClassInfo.pFullConfigDescriptor,
- i,
- &pInterfaceDescriptor);
- BlockCopy( (void *)pInterfaceDescriptor,
- (void *)(&(gStorageClassInfo.interfaceDescriptors[i])),
- (Size)(pInterfaceDescriptor->length));
- }
-
- gStorageClassInfo.pInterfaceDescriptor = &(gStorageClassInfo.interfaceDescriptors[0]);
-
- gStorageClassInfo.interfaceIndex = 0;
- gStorageClassInfo.interfaceCount = gStorageClassInfo.partialConfigDescriptor.numInterfaces;
- usbPB->usbRefcon = kFindStorageInterface;
- break;
-
- case kFindStorageInterface:
- gStorageClassInfo.interfaceNumber = usbPB->usb.cntl.WIndex;
- usbPB->usbRefcon = kNewInterfaceRef;
- break;
-
- case kNewInterfaceRef:
- gStorageClassInfo.interfaceRef = usbPB->usbReference;
- usbPB->usbRefcon = kStorageConfigureInterface;
- break;
-
- case kStorageConfigureInterface:
- usbPB->usbRefcon = kStorageFindInterruptPipe;
- break;
-
- case kStorageFindInterruptPipe:
- gStorageClassInfo.interruptPipeRef = usbPB->usbReference;
- usbPB->usbRefcon = kStorageFindBulkInPipe;
- break;
-
- case kStorageFindBulkInPipe:
- gStorageClassInfo.readPipeRef = usbPB->usbReference;
- usbPB->usbRefcon = kStorageFindBulkOutPipe;
- break;
-
- case kStorageFindBulkOutPipe:
- gStorageClassInfo.writePipeRef = usbPB->usbReference;
- gConfigured = true; // Set the configured flag so we can respond to calls via the dispatch table
- gConfigureStatus = kConfigureComplete; // Flag for client to determine that we are no configured
- IF_DEBUG(USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClass: Driver Configured.", 3 ) );
- usbPB->usbRefcon = kReturnFromDriver;
- break;
-
- case kStorageReadInterrupt:
- // ProcessStorageInterrupt(pStoragePB);
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClass: kStorageReadInterrupt. Byte 0:", gStorageClassInfo.interruptReport[0] ));
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClass: kStorageReadInterrupt. Byte 1:", gStorageClassInfo.interruptReport[1] ));
-
- usbPB->usbRefcon = kStorageReadInterrupt;
- break;
-
- case kNilCompletion:
- default:
- if ( usbPB->usbStatus == noErr )
- usbPB->usbRefcon = kUndefined | kReturnFromDriver;
- break;
- }
- }
-
- if ( usbPB->usbStatus == noErr )
- {
- if (!(usbPB->usbRefcon & kReturnFromDriver))
- StorageDeviceInitiateConfiguration(usbPB);
- }
- else
- {
- gConfigureStatus = kConfigureFailed;
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, usbPB->usbStatus, StateStr(usbPB->usbRefcon, kPString), usbPB->usbRefcon) );
- IF_DEBUG( USBExpertFatalError(gStorageClassInfo.deviceRef, usbPB->usbStatus, USBStatusStr(usbPB->usbStatus, kPString), 0) );
- }
- }
-
-
- void
- StorageDriverEntry( USBDeviceRef deviceRef,
- USBDeviceDescriptorPtr deviceDescriptorPtr,
- USBInterfaceDescriptorPtr pInterfaceDescriptor)
- {
- UInt32 usbVersion;
-
- IF_DEBUG( USBExpertStatus(deviceRef, "\pStorage Driver Entry" , 1 ) );
-
- if( !gBeenThereDoneThat)
- {
- gBeenThereDoneThat = true;
-
- // Check for the correct version of the USB manager.
- // We are ok with all version later than 1.0
-
- if (GetUSBVersion(&usbVersion) == noErr)
- {
- if ((usbVersion & 0xffff0000) < 0x01010000) // Wrong USB version number so do NOT continue
- {
- IF_DEBUG( USBExpertStatus(deviceRef, "\pWrong version of the USB Manager" , 1 ) );
-
- IF_DEBUG( USBExpertFatalError(deviceRef, 0, "\pWrong USB Manager version" , 0) );
- gConfigured = false; // Set the configured flag so we can respond to calls via the dispatch table
- gConfigureStatus = kConfigureFailed; // Flag for client to determine that configuration failed
-
- return ;
- }
- }
-
- // Initialize the global data structures
- BlockZero(&gStorageClassInfo, sizeof(StorageClassInfo));
- BlockZero(&gInterruptPB, sizeof(StorageClassTransactionPB));
- BlockZero(&gCommandPB, sizeof(StorageClassTransactionPB));
-
- gStorageClassInfo.retryCount = kStorageRetryCount;
- gStorageClassInfo.deviceDescriptor = *deviceDescriptorPtr; // keep a copy of the device descriptor
- gStorageClassInfo.pInterfaceDescriptor = pInterfaceDescriptor;
- gStorageClassInfo.deviceRef = deviceRef;
- gStorageClassInfo.interfaceRef = deviceRef;
- gStorageClassInfo.transDepth = 0; // init Delay Callback Depth
-
- InitParamBlock( deviceRef, &gStorageClassInfo.usbPB );
-
- // Start out at first state
- if (gStorageClassInfo.pInterfaceDescriptor != NULL)
- {
- gStorageClassInfo.usbPB.usbRefcon = kStorageConfigureInterface;
- IF_DEBUG( USBExpertStatus(deviceRef, "\pStart as interface driver" , 0 ) );
- }
- else
- {
- gStorageClassInfo.usbPB.usbRefcon = kGetFullConfiguration;
- IF_DEBUG( USBExpertStatus(deviceRef, "\pStart as device driver" , 0 ) );
- }
-
- gConfigureStatus = kConfigureInProgress;
- StorageDeviceInitiateConfiguration(&gStorageClassInfo.usbPB);
- }
- }
-
-
- void
- StorageClassDriverFinalize( void )
- {
- OSStatus status;
-
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriverFinalize." , 0 ) );
-
- //
- // Make sure all pipes are finished with transactions by calling the USBAbortPipeByReference function
- //
- status = USBAbortPipeByReference(gStorageClassInfo.deviceRef); // Control pipe
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pUSBAbortPipeByReference: Control pipe" , status ) );
-
- status = USBAbortPipeByReference(gStorageClassInfo.interruptPipeRef); // Interrupt pipe
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pUSBAbortPipeByReference: Interrupt pipe" , status ) );
-
- status = USBAbortPipeByReference(gStorageClassInfo.readPipeRef); // Read pipe
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pUSBAbortPipeByReference: Read pipe" , status ) );
-
- status = USBAbortPipeByReference(gStorageClassInfo.writePipeRef); // Write pipe
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pUSBAbortPipeByReference: Write pipe" , status ) );
- }
-
-
- OSStatus
- StorageClassDriverNotifyProc(UInt32 notification, void* pointer)
- {
- #pragma unused (notification, pointer)
- OSStatus status = noErr;
-
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriverNotifyProc. gConfigureStatus: " , gConfigureStatus ) );
- IF_DEBUG( USBExpertStatus(gStorageClassInfo.deviceRef, "\pStorageClassDriverNotifyProc. gOKToRemoval: " , gOKToRemoval ) );
-
- // Don't allow removal if we are busy configuration the interface.
- if (gConfigureStatus == kConfigureInProgress)
- {
- status = kUSBDeviceBusy;
- }
-
- // Don't allow removal until the Shim says it's ok
- if (gOKToRemoval == false)
- {
- status = kUSBDeviceBusy;
- }
-
- return (status);
- }
-